package com.ruoyi.web.controller.system;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.chinaums.open.api.OpenApiCache;
import com.chinaums.open.api.OpenApiContext;
import com.chinaums.open.api.constants.ConfigBean;
import com.chinaums.open.api.internal.util.http.HttpTransport;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.service.ISysDeptService;
import io.swagger.v3.oas.models.security.SecurityScheme;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.UUID;

/**
 * api
 *
 * @author Lion Li
 */
@Validated
@RequiredArgsConstructor
@RestController
@SaIgnore
@RequestMapping("/bc/v1")
public class BCApiController extends BaseController {
    private final ISysDeptService deptService;


    static String appId = "8a81c1bf89b6ccf7018b5b30aac10b83";
    static String appKey = "0489f0e4963f4fdcb62c3b6d46755772";
    static String termBatchNoOut = "000001";

    static String merchantCode = "8984601701199KU";
    static String terminalCode = "84JZ80E9";
    static String transactionCurrencyCode = "156";
    static String ip = "112.66.183.207";
    static String deviceType = "11";
    static String invocationMode="POLL";



    // 定义格式化器
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HHmmss");
    DateTimeFormatter formatterTwo = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");

    //快速担保完成
    @GetMapping("/quickcompleteauthorization")
    public R<Object> preauthcmp( String orderId, String transactionAmount, String params,String money) throws Exception {

        String url = "https://api-mop.chinaums.com/v1/poslink/transaction/preauthorization/quickcompleteauthorization";
        ConfigBean configBean = new ConfigBean();
        OpenApiContext context = new OpenApiContext();
        LocalTime now = LocalTime.now();
        String systemTraceNum=now.format(formatter);
        String request =
            "{" +
                "\"merchantCode\":\"" + merchantCode + "\"," +
                "\"terminalCode\":\"" + terminalCode + "\"," +
                "\"systemTraceNum\":\"" + systemTraceNum + "\"," +
                "\"transactionAmount\":\"" + transactionAmount + "\"," +
                "\"transactionCurrencyCode\":\"" + transactionCurrencyCode + "\"," +
                "\"orderId\":\"" + orderId + "\"" +
                "}";
        context.setStartTime(System.currentTimeMillis());
        context.setRequestId(UUID.randomUUID().toString().replace("-", ""));
        context.setOpenServUrl(url.split("/v")[0].concat("/"));
        System.out.println(context.getOpenServUrl() + "========================================================================================================================");
        context.setApiServiceUrl(url);
        context.setVersion(url.split("/")[3]);
        context.setAppId(appId);
        context.setAppKey(appKey);
        context.setConfigBean(configBean);
        context.setServiceCode(url.split("/v")[1].substring(1));
        OpenApiCache.getCurrentToken(context);
        String s = HttpTransport.getInstance().doPost(context, request);
        Map maps = (Map) JSONUtil.parse(s);
        if (maps.get("errCode").equals("00")) {
            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
            String urls = "jdbc:sqlserver://172.31.0.17:1433;DatabaseName=Training;trustServerCertificate=true;";
            Connection conn = DriverManager.getConnection(urls, "sa", "SUNSHINE@123,.HNA");
            String[] paramList = params.split(",");
            String reservationCode = paramList[0];   //预定号
            PreparedStatement ps = conn.prepareStatement("{call dbo.ftPayment(?,?,?,?,?,?,?,?,?,?,?)}");
            ps.setString(1, "9004");
            ps.setString(2, money);
            ps.setString(3, "0|0|0");
            ps.setString(4, "bc担保快速完成|订单号"+orderId);
            ps.setString(5, null);
            ps.setString(6, null);
            ps.setString(7, "*");
            ps.setString(8, "*");
            ps.setInt(9, 1);
            ps.setInt(10, Integer.parseInt(reservationCode));
            ps.setString(11, "Admin");

            ps.execute();
            return R.ok("操作成功", maps.get("errInfo"));
        }
//
//        String now = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_FORMAT);
//        JSONObject json = new JSONObject();
//        json.set("merchantCode", merchantCode);
//        json.set("terminalCode", terminalCode);
//        json.set("systemTraceNum", systemTraceNum);
//        json.set("transactionAmount", transactionAmount);
//        json.set("transactionCurrencyCode", transactionCurrencyCode);
//        json.set("orderId", orderId);
//
//        //2. 获取认证报文，timestamp为当前日期，老旧日期无法请求成功
//        String authorization = getAuthorization(appId, appKey, now, IdUtil.fastSimpleUUID(), JSONUtil.toJsonStr(json));
//
//        String re = HttpRequest.post(url)
//            .body(JSONUtil.toJsonStr(json))
//            .header("authorization", authorization).execute().body();
//        Map<String, String> map = (Map) JSONUtil.parseObj(re);
//
//        String respCodeDesc = map.get("errInfo");

        return R.ok("操作失败", maps.get("errInfo"));
    }


    //快速担保撤销
    @GetMapping("/quickvoidauthorization")
    public R<Object> quickvoidauthorization(String orderId, String transactionAmount,String params) throws Exception {

        String url = "https://api-mop.chinaums.com/v1/poslink/transaction/preauthorization/quickvoidauthorization";
        ConfigBean configBean = new ConfigBean();
        OpenApiContext context = new OpenApiContext();
        LocalTime now = LocalTime.now();
        String systemTraceNum=now.format(formatter);
        String request =
            "{" +
                "\"merchantCode\":\"" + merchantCode + "\"," +
                "\"terminalCode\":\"" + terminalCode + "\"," +
                "\"systemTraceNum\":\"" + systemTraceNum + "\"," +
                "\"transactionAmount\":\"" + transactionAmount + "\"," +
                "\"transactionCurrencyCode\":\"" + transactionCurrencyCode + "\"," +
                "\"orderId\":\"" + orderId + "\"" +
                "}";
        context.setStartTime(System.currentTimeMillis());
        context.setRequestId(UUID.randomUUID().toString().replace("-", ""));
        context.setOpenServUrl(url.split("/v")[0].concat("/"));
        System.out.println(context.getOpenServUrl() + "========================================================================================================================");
        context.setApiServiceUrl(url);
        context.setVersion(url.split("/")[3]);
        context.setAppId(appId);
        context.setAppKey(appKey);
        context.setConfigBean(configBean);
        context.setServiceCode(url.split("/v")[1].substring(1));
        OpenApiCache.getCurrentToken(context);
        String s = HttpTransport.getInstance().doPost(context, request);
        Map maps = (Map) JSONUtil.parse(s);
        if (maps.get("errCode").equals("00")) {
            deptService.deleteBank(orderId);
            deptService.deleteBankCard(orderId);
            return R.ok("操作成功", maps.get("errInfo"));
        }
//        String now = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_FORMAT);
//        JSONObject json = new JSONObject();
//        json.set("merchantCode", merchantCode);
//        json.set("terminalCode", terminalCode);
//        json.set("systemTraceNum", systemTraceNum);
//        json.set("transactionAmount", transactionAmount);
//        json.set("transactionCurrencyCode", transactionCurrencyCode);
//        json.set("orderId", orderId);
//
//        //2. 获取认证报文，timestamp为当前日期，老旧日期无法请求成功
//        String authorization = getAuthorization(appId, appKey, now, IdUtil.fastSimpleUUID(), JSONUtil.toJsonStr(json));
//
//        String re = HttpRequest.post(url)
//            .body(JSONUtil.toJsonStr(json))
//            .header("authorization", authorization).execute().body();
//        Map<String, String> map = (Map) JSONUtil.parseObj(re);
//        String respCodeDesc = map.get("errInfo");

        return R.ok("操作失败", maps.get("errInfo"));
    }

    //交易
    @GetMapping("/pay")
    public R<Object> pay(
        String payCode, String payMode, String transactionAmount,String params,String money) throws Exception {

        String url = "https://api-mop.chinaums.com/v5/poslink/transaction/pay";

        ConfigBean configBean = new ConfigBean();
        OpenApiContext context = new OpenApiContext();
        LocalDateTime now = LocalDateTime.now();
        String merchantOrderId=now.format(formatterTwo);
        String merchantRemark="bc交易";
        String request =
            "{" +
                "\"merchantCode\":\"" + merchantCode + "\"," +
                "\"terminalCode\":\"" + terminalCode + "\"," +
                "\"transactionAmount\":\"" + transactionAmount + "\"," +
                "\"transactionCurrencyCode\":\"" + transactionCurrencyCode + "\"," +
                "\"merchantOrderId\":\"" + merchantOrderId + "\"," +
                "\"merchantRemark\":\"" + merchantRemark + "\"," +
                "\"payMode\":\"" + payMode + "\"," +
                "\"payCode\":\"" + payCode + "\"," +
                "\"invocationMode\":\"" + invocationMode + "\"," +
                "\"deviceType\":\"" + deviceType + "\"" +
                "}";
        context.setStartTime(System.currentTimeMillis());
        context.setRequestId(UUID.randomUUID().toString().replace("-", ""));
        context.setOpenServUrl(url.split("/v")[0].concat("/"));
        System.out.println(context.getOpenServUrl() + "========================================================================================================================");
        context.setApiServiceUrl(url);
        context.setVersion(url.split("/")[3]);
        context.setAppId(appId);
        context.setAppKey(appKey);
        context.setConfigBean(configBean);
        context.setServiceCode(url.split("/v")[1].substring(1));
        OpenApiCache.getCurrentToken(context);
        String s = HttpTransport.getInstance().doPost(context, request);
        Map maps = (Map) JSONUtil.parse(s);
        if (maps.get("errCode").equals("00")) {
            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
            String urls = "jdbc:sqlserver://172.31.0.17:1433;DatabaseName=Training;trustServerCertificate=true;";
            Connection conn = DriverManager.getConnection(urls, "sa", "SUNSHINE@123,.HNA");
            String[] paramList = params.split(",");
            String reservationCode = paramList[0];   //预定号
            PreparedStatement ps = conn.prepareStatement("{call dbo.ftPayment(?,?,?,?,?,?,?,?,?,?,?)}");
            ps.setString(1, "9004");
            ps.setString(2, money);
            ps.setString(3, "0|0|0");
            ps.setString(4, "bc交易订单号:"+merchantOrderId);
            ps.setString(5, null);
            ps.setString(6, null);
            ps.setString(7, "*");
            ps.setString(8, "*");
            ps.setInt(9, 1);
            ps.setInt(10, Integer.parseInt(reservationCode));
            ps.setString(11, "Admin");

            ps.execute();
            return R.ok("操作成功", maps.get("errInfo"));
        }
        return R.ok("操作失败", maps.get("errInfo"));
    }


    //撤销
    @GetMapping("/voidpayment")
    public R<Object> voidpayment(
        String merchantOrderId,String params) throws Exception {

        String url = "https://api-mop.chinaums.com/v2/poslink/transaction/voidpayment";
        ConfigBean configBean = new ConfigBean();
        OpenApiContext context = new OpenApiContext();
        String request =
            "{" +
                "\"merchantCode\":\"" + merchantCode + "\"," +
                "\"terminalCode\":\"" + terminalCode + "\"," +
                "\"merchantOrderId\":\"" + merchantOrderId + "\"" +
                "}";
        context.setStartTime(System.currentTimeMillis());
        context.setRequestId(UUID.randomUUID().toString().replace("-", ""));
        context.setOpenServUrl(url.split("/v")[0].concat("/"));
        System.out.println(context.getOpenServUrl() + "========================================================================================================================");
        context.setApiServiceUrl(url);
        context.setVersion(url.split("/")[3]);
        context.setAppId(appId);
        context.setAppKey(appKey);
        context.setConfigBean(configBean);
        context.setServiceCode(url.split("/v")[1].substring(1));
        OpenApiCache.getCurrentToken(context);
        String s = HttpTransport.getInstance().doPost(context, request);
        Map maps = (Map) JSONUtil.parse(s);
        if (maps.get("errCode").equals("00")) {
            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
            String urls = "jdbc:sqlserver://172.31.0.17:1433;DatabaseName=Training;trustServerCertificate=true;";
            Connection conn = DriverManager.getConnection(urls, "sa", "SUNSHINE@123,.HNA");
            String[] paramList = params.split(",");
            String reservationCode = paramList[0];   //预定号
            PreparedStatement ps = conn.prepareStatement("{call dbo.ftPayment(?,?,?,?,?,?,?,?,?,?,?)}");
            ps.setString(1, "9004");
            ps.setDouble(2,  (double) ((int)maps.get("transactionAmount"))/100 * -1);
            ps.setString(3, "0|0|0");
            ps.setString(4, "bc交易撤销订单号:"+merchantOrderId);
            ps.setString(5, null);
            ps.setString(6, null);
            ps.setString(7, "*");
            ps.setString(8, "*");
            ps.setInt(9, 1);
            ps.setInt(10, Integer.parseInt(reservationCode));
            ps.setString(11, "Admin");

            ps.execute();
            return R.ok("操作成功", maps.get("errInfo"));
        }
        return R.ok("操作失败", maps.get("errInfo"));
    }


    @SneakyThrows
    static String getAuthorization(String appid, String appkey, String timestamp, String nonce, String body) {
        byte[] data = body.getBytes(StandardCharsets.UTF_8);
        InputStream is = new ByteArrayInputStream(data);
        String testSH = DigestUtils.sha256Hex(is);
        String s1 = appid + timestamp + nonce + testSH;
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(appkey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] localSignature = mac.doFinal(s1.getBytes(StandardCharsets.UTF_8));
        String localSignatureStr = Base64.encodeBase64String(localSignature);
        return "OPEN-BODY-SIG AppId=" + "\"" + appid + "\"" + ", Timestamp=" + "\"" + timestamp + "\"" + ", Nonce=" + "\"" + nonce + "\"" + ", Signature=" + "\"" + localSignatureStr + "\"";
    }
}


